package com.yanqu.xiuxian.config.elementalbonds;

import com.yanqu.xiuxian.config.annotations.ConfigAnnotation;
import com.yanqu.xiuxian.config.param.BaseParamConfigMgr;
import com.yanqu.xiuxian.config.param.GameConfig;
import com.yanqu.xiuxian.config.utils.excel.StringUtils;
import com.yanqu.xiuxian.utils.TimeUtils;
import com.yanqu.xiuxian.utils.date.DateHelper;
import com.yanqu.xiuxian.utils.property.PropArrayConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class ElementalBondsParam extends BaseParamConfigMgr {
    private static final Logger log = LoggerFactory.getLogger(ElementalBondsParam.class);
    private static ElementalBondsParam instance = new ElementalBondsParam();

    public static ElementalBondsParam getInstance() {
        return instance;
    }

    @ConfigAnnotation(key = "ELEMENTALBONDS_TITLE_LIMIT", comment = "夺魁-每个赛季积分重置为N")
    private int initScore;
    @ConfigAnnotation(key = "ELEMENTALBONDS_RANK_LIMIT", comment = "夺魁-排行榜最低积分")
    private int rankScoreLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_RANK_NUM", comment = "夺魁-排行榜显示上限")
    private int rankNum;
    @ConfigAnnotation(key = "ELEMENTALBONDS_DAILY_QUEST_NUM", comment = "夺魁-每日任务数量")
    private int dailyQuestNum;
    @ConfigAnnotation(key = "ELEMENTALBONDS_DAILY_QUEST_LIMIT", comment = "夺魁-每日任务上限")
    private int dailyQuestLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_WEEKLY_QUEST_NUM", comment = "夺魁-每周任务数量")
    private int weeklyQuestNum;
    @ConfigAnnotation(key = "ELEMENTALBONDS_WEEKLY_QUEST_LIMIT", comment = "夺魁-每周任务上限")
    private int weeklyQuestLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_OFFLINE_RECONNECT", comment = "夺魁-断线重连")
    private List<Integer> offlineReconnect;
    @ConfigAnnotation(key = "ELEMENTALBONDS_STREAK_WIN", comment = "夺魁-连胜场数|积分倍率千分比")
    private List<Integer> streakWin;
    @ConfigAnnotation(key = "ELEMENTALBONDS_ITEM_ID_SHIELD", comment = "护盾id")
    private int itemIdShield;
    @ConfigAnnotation(key = "ELEMENTALBONDS_ITEM_ID_MONEY", comment = "夺魁-玄晶id")
    private int itemIdMoney;
    @ConfigAnnotation(key = "ELEMENTALBONDS_BUY_BAG_COLD_TIME", comment = "夺魁-买礼包时礼包冷却时间，单位：秒")
    private int buyBagColdTime;
    @ConfigAnnotation(key = "ELEMENTALBONDS_BAG_CONTINUE_TIME", comment = "夺魁-礼包有效时间，单位：秒")
    private int bagContinueTime;
    @ConfigAnnotation(key = "ELEMENTALBONDS_DAY_SURRENDER_TIMES", comment = "每日投降次数上限")
    private int daySurrenderTimes;
    @ConfigAnnotation(key = "ELEMENTALBONDS_FIGHT_SCENE_OPEN_LIMIT", comment = "盘面机制开启需要玩家分数")
    private int fightSceneOpenLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_EXTEND_TIME", comment = "匹配搜寻扩展段位范围时间（秒）", parseMethod = "parseMatchExtendTime")
    private List<Long> matchExtendTimeList = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_NEED_PLAYER_NUM_2", comment = "匹配需要段位范围内玩家数量", parseMethod = "parseMatchNeedPlayerNum")
    private List<List<Integer>> matchNeedPlayerNumList = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_SKILL_ID_USE_LIMIT", comment = "夺魁-盘面技能一局使用次数")
    private int skillIdUseLimit = 1;
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_NPC_SCORE", comment = "夺魁-小于等于这个分数，一直匹配npc")
    private int matchNpcScore;
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_OUT_TIME", comment = "夺魁-匹配超过此时间则匹配机器人（秒，按ELEMENTALBONDS_AI_HARD字段确定难度）")
    private int matchOutTime;
    @ConfigAnnotation(key = "ELEMENTALBONDS_GUIDE_MATCH_NPC_TIME", comment = "夺魁-新手段位匹配超过x秒匹配NPC")
    private int guideMatchNpcTime;
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_OUT_SCORE_LIMIT", comment = "夺魁-匹配不到人直接匹配NPC需要分数小于")
    private int matchOutScoreLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_AI_RED_CARD_LIMIT", comment = "夺魁-小于这个分数的机器人不会使用红卡")
    private int aiRedCardLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_AI_MATCH_CARD_2", comment = "夺魁-AI卡牌品质（段位起始;段位结束;品质小1权重;品质相同权重;品质加1权重）", parseMethod = "parseAiMatchCard")
    private List<List<Integer>> aiMatchCard = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_FIGHT_SCENE_WEIGHT_BEGIN", comment = "夺魁-每种玩法初始权重")
    private int sceneBaseWeight;
    @ConfigAnnotation(key = "ELEMENTALBONDS_FIGHT_SCENE_WEIGHT_ADD", comment = "夺魁-上一日未抽中玩法则增加该玩法权重")
    private int sceneWeightAdd;
    @ConfigAnnotation(key = "ELEMENTALBONDS_FIGHT_SCENE_RANDOM_NUM", comment = "夺魁-随机玩法数量")
    private int sceneDayNum;
    @ConfigAnnotation(key = "ELEMENTALBONDS_DISCONNECT_FAIL_FIRST_LIMIT", comment = "夺魁-刚进游戏掉线超过此配置值，才计算掉线次数（秒）")
    private int disconnectFailFirstLimit;
    @ConfigAnnotation(key = "ELEMENTALBONDS_TIME_LIMIT_TASK", comment = "夺魁-限时任务开启参数.持续时间|间隔时间;", parseMethod = "parseTimeLimitTask")
    private List<List<Integer>> timeLimitTaskList = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_EXTRA_BONUS_REWARD", comment = "夺魁-额外权益奖励;")
    private PropArrayConfig extraBonusReward;
    @ConfigAnnotation(key = "ELEMENTALBONDS_EXTRA_MATCH_RULE", comment = "夺魁-匹配技能卡上下浮动.上|下")
    private List<Integer> extraMatchRule;
    @ConfigAnnotation(key = "ELEMENTALBONDS_EXTRA_MATCH_RATE", comment = "夺魁-匹配胜率上下浮动.上|下")
    private List<Integer> extraMatchRate;
    @ConfigAnnotation(key = "ELEMENTALBONDS_SPECIAL_ITEM_ID", comment = "夺魁-特殊技能道具(技能id)")
    private List<Integer> specialItemIdList;
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_TIME_LIMIT", comment = "夺魁-匹配时间限制", parseMethod = "parseMatchTimeLimit")
    private List<List<Integer>> matchTimeLimitList = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_MATCH_TIME_LIMIT_SCORE", comment = "夺魁-匹配时间限制分数", parseMethod = "parseMatchTimeLimitScore")
    private List<List<Integer>> matchTimeLimitScoreList = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_PERIOD_TIME", comment = "夺魁-阶段时间。1-展示期，2-领奖期。单位分钟", parseMethod = "parseElementalBondsPeriodTime")
    private Map<Integer, Integer> periodTimeMap = new HashMap<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_POINTS_PARAM-1", comment = "夺魁-积分参数1。积分每低于对方N1|增加N2的分数|最多增加N3分")
    private List<Integer> pointsParam1 = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_POINTS_PARAM-2", comment = "夺魁-积分参数2。夺魁-积分参数2。胜利时使用的卡牌比品质比对方低n的时候的额外积分。")
    private List<Integer> pointsParam2 = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_POINTS_PARAM-3", comment = "夺魁-积分参数3。失败时使用的卡牌比品质比对方低n的时候的额外积分。")
    private List<Integer> pointsParam3 = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_COIN_PARAM", comment = "夺魁-金币参数。胜利获得金币|失败获得金币")
    private List<Integer> coinParam = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_SCORE_PARAM", comment = "夺魁-符魂参数。符魂对应限时任务积分", parseMethod = "parseScoreParam")
    private Map<Integer, Integer> scoreParam = new HashMap<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_ORIGIN_CARD", comment = "夺魁-初始解锁的卡牌")
    private List<Integer> originCard = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTAL_BONDS_DEFAULT_MEME", comment = "夺魁-默认表情包")
    private List<Integer> defaultMeme = new ArrayList<>();

    // AI
    @ConfigAnnotation(key = "ELEMENTALBONDS_AI_MOVE_TIME", comment = "夺魁-ai操作时间")
    private List<Integer> aiOperateTimeList = new ArrayList<>();                                                     // AI操作时间，[段位起始，段位结束，时间1，时间2，时间3]
    @ConfigAnnotation(key = "ELEMENTALBONDS_AI_HARD", comment = "夺魁-ai难度", parseMethod = "parseAiHard")
    private List<List<Integer>> aiHardList = new ArrayList<>();                                                     // AI难度，[段位起始，段位结束，难度1权重，难度2权重，难度3权重]
    @ConfigAnnotation(key = "ELEMENTALBONDS_AI_APPEARANCE", comment = "夺魁-AI主角形象随机列表")
    private List<Integer> aiAppearance = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_AI_HEAD", comment = "夺魁-AI主角头像随机列表")
    private List<Integer> aiHeadList = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_NPC_NAME_NUM", comment = "夺魁-NPC名字AI名字数量")
    private int npcNameNum;

    // 战斗
    @ConfigAnnotation(key = "ELEMENTALBONDS_FIGHT_BLOCK_SCORE", comment = "夺魁-方块分数")
    private int blockScore;
    @ConfigAnnotation(key = "ELEMENTALBONDS_STAR_ELIMINATE_NUM", comment = "流星炸弹消除方块数")// 每个方块分数
    private int meteorEliminateNum;
    @ConfigAnnotation(key = "ELEMENTALBONDS_CREATE_BLOCK_PARAM", comment = "夺魁-方块重置权重；权重增加值；增加权重条件：小于n个；下落如果会消除则替换该方块的概率", parseMethod = "parseCreateBlockParam")
    private List<Integer> createBlockParam = new ArrayList<>();
    @ConfigAnnotation(key = "ELEMENTALBONDS_CREATE_OLD_KEEP_ROUND", comment = "夺魁-维持原掉落规则的回合数（<=)")
    private int drop2OpenRound;                                                                 // 掉落规则2：开启回合
    @ConfigAnnotation(key = "ELEMENTALBONDS_CREATE_NEW_RULE_PARAM", comment = "夺魁-掉落参数a|b|c1|c2")
    private List<Integer> drop2List;                                                            // 掉落规则2：参数a|b|c1|c2

    private long expressionInterval = DateHelper.SECOND_MILLIONS * 2;
    // 发送表情间隔时间
    @ConfigAnnotation(key = "ELEMENTALBONDS_NEW_RULE_USE", comment = "夺魁-新规则开关（1表示使用；0表示采用旧规则）")
    private int useNewRule = 0;     // 发送表情间隔时间     // 新规则开关(消除规则 1 开，0关)

    private ElementalBondsParam() {
    }

    @Override
    public void refresh(Map<String, GameConfig> configMap) {
        parseParam(instance, configMap);
    }

    // 获取掉线时间，超出后就失败了
    public long getDisconnFailTime(int hadDisconnTimes) {
        int index = Math.min(offlineReconnect.size() - 1, hadDisconnTimes);
        return offlineReconnect.get(index);
    }

    public int getInitScore() {
        return initScore;
    }

    public int getRankScoreLimit() {
        return rankScoreLimit;
    }

    public int getRankNum() {
        return rankNum;
    }

    public int getDailyQuestNum() {
        return dailyQuestNum;
    }

    public int getDailyQuestLimit() {
        return dailyQuestLimit;
    }

    public List<Integer> getStreakWin() {
        return streakWin;
    }

    public int getWeeklyQuestNum() {
        return weeklyQuestNum;
    }

    public int getWeeklyQuestLimit() {
        return weeklyQuestLimit;
    }

    public List<Integer> getOfflineReconnect() {
        return offlineReconnect;
    }

    public int getDisconnectTime(int counts) {
        if (counts >= offlineReconnect.size()) {
            return offlineReconnect.get(offlineReconnect.size() - 1);
        }
        return offlineReconnect.get(counts );
    }

    public List<Integer> getAiOperateTimeList() {
        return aiOperateTimeList;
    }

    public List<List<Integer>> getAiHardList() {
        return aiHardList;
    }

    public int getBlockScore() {
        return blockScore;
    }

    public int getMeteorEliminateNum() {
        return meteorEliminateNum;
    }

    public int getDropBaseWeight() {
        return createBlockParam.get(0);
    }

    public int getDropAddiWeight() {
        return createBlockParam.get(1);
    }

    public int getDropAddiCountLimit() {
        return createBlockParam.get(2);
    }

    public int getDropStableWeight() {
        return createBlockParam.get(3);
    }

    public int getDrop2OpenRound() {
        return drop2OpenRound;
    }

    public List<Integer> getDrop2List() {
        return drop2List;
    }

    public long getExpressionInterval() {
        return expressionInterval;
    }

    public int getUseNewRule() {
        return useNewRule;
    }

    public int getItemIdShield() {
        return itemIdShield;
    }

    public List<Integer> getAiAppearance() {
        return aiAppearance;
    }

    public int getItemIdMoney() {
        return itemIdMoney;
    }

    public int getDaySurrenderTimes() {
        return daySurrenderTimes;
    }

    public void parseAiHard(String aiHard) {
        List<List<Integer>> tmpList = new ArrayList<>();
        String[] hardList = aiHard.split("\\|");
        for (String hard : hardList) {
            String[] hardInfo = hard.split(";");
            List<Integer> hardInfoList = new ArrayList<>();
            for (String info : hardInfo) {
                hardInfoList.add(Integer.parseInt(info));
            }
            tmpList.add(hardInfoList);
        }
        this.aiHardList = tmpList;
    }

    public void parseCreateBlockParam(String createBlockParam) {
        this.createBlockParam = StringUtils.stringToIntegerList(createBlockParam, ";");

    }

    public int getBagContinueTime() {
        return bagContinueTime;
    }

    public int getBuyBagColdTime() {
        return buyBagColdTime;
    }

    public int getFightSceneOpenLimit() {
        return fightSceneOpenLimit;
    }

    // 获取匹配范围扩大次数
    public int getMatchExtendTimes(long matchCostTime) {
        long copyTime = matchCostTime;
        int times = 0;

        // 前N-1档一个个扩展
        for (int i = 0; i < matchExtendTimeList.size() - 1; i++) {
            if (copyTime >= matchExtendTimeList.get(i)) {
                copyTime -= matchExtendTimeList.get(i);
                times++;
            } else {
                return times; // 扩展失败
            }
        }

        // 前N-1档都扩展完了，最后一档用除的计算
        long lastValue = matchExtendTimeList.get(matchExtendTimeList.size() - 1);
        if (copyTime > 0 && lastValue > 0) {
            times = times + (int) (copyTime / lastValue);
        }

        return times;
    }

    public void parseMatchNeedPlayerNum(String str) {
        List<List<Integer>> tmpList = new ArrayList<>();
        for (String tmp : StringUtils.stringToStringList(str, "\\|")) {
            tmpList.add(StringUtils.stringToIntegerList(tmp, ";"));
        }
        this.matchNeedPlayerNumList = tmpList;
    }

    // 获取匹配所需玩家数量
    public int getMatchNeedPlayerNum(int rankId) {
        int num = matchNeedPlayerNumList.get(0).get(1);
        for (List<Integer> list : matchNeedPlayerNumList) {
            if (rankId >= list.get(0)) num = list.get(1);
            else break;
        }
        return num;
    }

    public int getSkillIdUseLimit() {
        return skillIdUseLimit;
    }

    public int getMatchOutTime() {
        return matchOutTime;
    }

    public int getMatchNpcScore() {
        return matchNpcScore;
    }

    public List<Integer> getAiHeadList() {
        return aiHeadList;
    }

    public int getNpcNameNum() {
        return npcNameNum;
    }

    public int getGuideMatchNpcTime() {
        return guideMatchNpcTime;
    }

    public int getMatchOutScoreLimit() {
        return matchOutScoreLimit;
    }

    public int getAiRedCardLimit() {
        return aiRedCardLimit;
    }

    public void parseAiMatchCard(String str) {
        List<List<Integer>> tmpList = new ArrayList<>();
        for (String aiHard : StringUtils.stringToStringList(str, "\\|")) {
            tmpList.add(StringUtils.stringToIntegerList(aiHard, ";"));
        }
        this.aiMatchCard = tmpList;
    }

    // 获取人机随机卡牌品质的权重
    public List<Integer> getAiCardQuaWeightList(int rankId) {
        List<Integer> result = null;

        for (List<Integer> list : aiMatchCard) {
            if (list.get(0) <= rankId && rankId <= list.get(1)) {
                result = list;
                break;
            }
        }
        if (result == null) {
            result = aiMatchCard.get(aiMatchCard.size() - 1);
        }

        result = new ArrayList<>(result);
        result.remove(0);
        result.remove(0);
        return result;
    }

    public int getSceneBaseWeight() {
        return sceneBaseWeight;
    }

    public int getSceneWeightAdd() {
        return sceneWeightAdd;
    }

    public int getSceneDayNum() {
        return sceneDayNum;
    }

    public int getDisconnectFailFirstLimit() {
        return disconnectFailFirstLimit;
    }

    public void parseTimeLimitTask(String str) {
        List<List<Integer>> tmpList = new ArrayList<>();
        for (String aiHard : StringUtils.stringToStringList(str, ";")) {
            tmpList.add(StringUtils.stringToIntegerList(aiHard, "\\|"));
        }
        this.timeLimitTaskList = tmpList;
    }

    public List<List<Integer>> getTimeLimitTaskList() {
        return timeLimitTaskList;
    }

    public PropArrayConfig getExtraBonusReward() {
        return extraBonusReward;
    }

    public List<Integer> getExtraMatchRule() {
        return extraMatchRule;
    }

    public List<Integer> getExtraMatchRate() {
        return extraMatchRate;
    }

    public List<Integer> getSpecialItemIdList() {
        return specialItemIdList;
    }

    public List<Integer> getOriginCard() {
        return originCard;
    }

    public List<Integer> getCoinParam() {
        return coinParam;
    }

    public List<Integer> getDefaultMeme() {
        return defaultMeme;
    }

    public void parseMatchTimeLimit(String str) {
        List<List<Integer>> tmpList = new ArrayList<>();
        for (String aiHard : StringUtils.stringToStringList(str, "\\|")) {
            tmpList.add(StringUtils.stringToIntegerList(aiHard, ";"));
        }
        this.matchTimeLimitList = tmpList;
    }

    public boolean canMatch() {
        long todayZeroTimeStamp = TimeUtils.getTodayZeroTimeStamp();
        long startMatchTime = todayZeroTimeStamp + matchTimeLimitList.get(0).get(1) * TimeUtils.MINUTE_MILLIS;
        long endMatchTime = todayZeroTimeStamp + matchTimeLimitList.get(1).get(0) * TimeUtils.MINUTE_MILLIS;
        return System.currentTimeMillis() >= startMatchTime && System.currentTimeMillis() <= endMatchTime;
    }


    public void parseElementalBondsPeriodTime(String str) {
        Map<Integer, Integer> tmpMap = new HashMap<>();
        String[] periodConfig = str.split("\\|");
        for (String period : periodConfig) {
            String[] configStr = period.split(":");
            if (configStr.length != 2) {
                throw new RuntimeException("夺魁阶段时间配置错误 " + str);
            }
            int periodId = Integer.parseInt(configStr[0]);
            int periodDuration = Integer.parseInt(configStr[1]);

            tmpMap.put(periodId, periodDuration);
        }
        if (!tmpMap.isEmpty()) {
            periodTimeMap = tmpMap;
        }
    }

    public Map<Integer, Integer> getPeriodTimeMap() {
        return periodTimeMap;
    }

    public long winScoreAdd(long scoreDiff) {
        if (scoreDiff <= 0) return 0;
        int param = pointsParam1.get(0);
        int addScore = pointsParam1.get(1);
        int maxAdd = pointsParam1.get(2);

        long willAdd = scoreDiff / param * addScore;

        return Math.min(willAdd, maxAdd);
    }

    public int reduceDemeritPoints(int cardQualityDiff) {
        if (cardQualityDiff < 0) return 0;
        if (cardQualityDiff >= pointsParam2.size()) {
            return pointsParam2.get(pointsParam2.size() - 1);
        }
        return pointsParam2.get(cardQualityDiff);
    }

    public int winMorePoints(int cardQualityDiff) {
        if (cardQualityDiff < 0) return 0;
        if (cardQualityDiff >= pointsParam3.size()) {
            return pointsParam3.get(pointsParam3.size() - 1);
        }
        return pointsParam3.get(cardQualityDiff);
    }

    public void parseScoreParam(String str) {
        String[] scoreParam = str.split("\\|");
        Map<Integer, Integer> tmpMap = new HashMap<>();
        for (String score : scoreParam) {
            String[] configStr = score.split("=");
            tmpMap.put(Integer.parseInt(configStr[0]), Integer.parseInt(configStr[1]));
        }
        this.scoreParam = tmpMap;
    }

    public int limitTaskItemNum(int fuhun) {
        return scoreParam.get(fuhun) == null ? 0 : scoreParam.get(fuhun);
    }

    public void parseMatchExtendTime(String str) {
        String[] matchExtendTime = str.split("\\|");
        List<Long> tmpList = new ArrayList<>();
        for (String config : matchExtendTime) {
            tmpList.add(Long.parseLong(config) * TimeUtils.SECONDS_MILLIS);
        }
        this.matchExtendTimeList = tmpList;
    }
}
